/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pl.abstractvoid.gui;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.table.AbstractTableModel;
import pl.abstractvoid.datamodel.parameters.SingleParameter;
import pl.abstractvoid.languages.LanguageProvider;

/**
 * Responsible for communication between the table components and the program
 * data model. Allows for bi-directional communication: changed in tabular
 * data is reflected in the distribution data and vice versa. This way when
 * new data is generated by running an R script, the component can load new
 * values directly from the altered objects.
 * @author Wojciech Szałapski
 * @author Ivo Zieliński
 */
public class EditableSingleParameterTableModel extends AbstractTableModel {

    private String[] visibleParameterNames;
    protected String[] parameterNames;
    protected TreeMap<String, SingleParameter> parameters;

    public EditableSingleParameterTableModel(TreeMap<String, SingleParameter> parameters) {
        this.parameters = parameters;
        visibleParameterNames = new String[parameters.size()];
        parameterNames = new String[parameters.size()];
        int column = 0;
        for (Map.Entry pair : parameters.entrySet()) {
            SingleParameter singleParameter = (SingleParameter) pair.getValue();
            parameterNames[column] = singleParameter.getParameterName();
            visibleParameterNames[column] = singleParameter.getVisibleParameterName();
            column++;
        }

    }

    public EditableSingleParameterTableModel(SingleParameter[] singleParameters) {
        parameters = new TreeMap<>();
        for (SingleParameter singleParameter : singleParameters) {
            parameters.put(singleParameter.getParameterName(), singleParameter);
        }
        visibleParameterNames = new String[parameters.size()];
        parameterNames = new String[parameters.size()];
        int column = 0;
        for (Map.Entry pair : parameters.entrySet()) {
            SingleParameter singleParameter = (SingleParameter) pair.getValue();
            parameterNames[column] = singleParameter.getParameterName();
            visibleParameterNames[column] = singleParameter.getVisibleParameterName();
            column++;
        }
    }

    @Override
    public int getColumnCount() {
        return visibleParameterNames.length;
    }

    public String[] getColumnNames() {
        return visibleParameterNames;
    }

    public void setColumnNames(String[] columnNames) {
        this.visibleParameterNames = columnNames;

    }

    public TreeMap<String, SingleParameter> getData() {
        return parameters;
    }

    public void setData(TreeMap<String, SingleParameter> parameters) {
        this.parameters = parameters;
    }

    @Override
    public int getRowCount() {
        return 1;
    }

    /**
     * Returns value that should be displayed in a cell. Takes rounding into
     * account.
     * @param row
     * @param col
     * @return 
     */
    @Override
    public Object getValueAt(int row, int col) {
        double d = parameters.get(parameterNames[col]).getParameterValue();
        if (parameters.get(parameterNames[col]).isIsInteger()) {
            return (long) d;
        }
        int decimalPlaces = (int) MainFrame.roundingMode;
        if (d >= 10) {
            decimalPlaces += (int) Math.floor(Math.log10(d));
        }
        BigDecimal bd = new BigDecimal(d);
        bd = bd.round(new MathContext(decimalPlaces));
        return bd.doubleValue();
    }

    @Override
    public String getColumnName(int col) {
        return visibleParameterNames[col];
    }

    /**
     * Checks if proper values has been entered into a cell, and modifies 
     * the distribution data.
     * @param value
     * @param row
     * @param col 
     */
    @Override
    public void setValueAt(Object value, int row, int col) {
        try {
            double newValue = Double.parseDouble((String) value);
            if (parameters.get(parameterNames[col]).isIsInteger()) {
                newValue = (long) newValue;
            }
            parameters.get(parameterNames[col]).setParameterValue(newValue);
        } catch (NumberFormatException nfe) {
            System.out.println(LanguageProvider.getInstance().getString("insertANumber"));
        }
    }

    @Override
    public boolean isCellEditable(int row, int col) {
        return true;
    }

    /**
     * Reloads visible parameter's names to show the change of the current
     * language.
     */
    public void reloadLanguage() {
        int column = 0;
        for (Map.Entry pair : parameters.entrySet()) {
            SingleParameter singleParameter = (SingleParameter) pair.getValue();
            visibleParameterNames[column] = singleParameter.getVisibleParameterName();
            column++;
        }
    }
}
